package gggameserver.testbed;

import gggameserver.compiler.GGCompiler;
import gggameserver.exceptions.GGProcessException;
import gggameserver.games.connection.GGConnection;
import gggameserver.util.GGUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class GGMirroredTestBed implements GGTestBed {

	private enum TYPE {COMPILE, RUN};
	
	private TYPE type = TYPE.COMPILE; 
	
	private GGLocalTestBed localTB;
	private String mirrorName;
	
	private boolean isValid = true;
	private Exception exception;
	public File m_compiledZip;
	public ArrayList m_commandline;

	public GGTestBedFactory m_tbf;
	public int m_nr;
	
	private StringBuilder log = new StringBuilder();
	
	public GGMirroredTestBed(String mirrorName, GGLocalTestBed localTB) {
		this.mirrorName = mirrorName;
		this.localTB = localTB;
		if (!this.localTB.isValid()) isValid = false;
	}
	
	public boolean initialize(GGTestBedFactory tbf, String language, int nr) throws IOException {
		m_nr = nr;
		m_tbf = tbf;
		if (!isValid()) return isValid();
		
		File file;
		
		try {
			file = localTB.zipTestBed();
		} catch (GGProcessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			isValid = false;
			return isValid();
		}
		
		if (!file.exists()) {
			isValid = false;
			return isValid();
		}
		
		//
		String testbedName = file.getName();
		testbedName = testbedName.substring(0, testbedName.length()-4);
		GGMirror mirror = tbf.getMirror(this.mirrorName + nr);

		try {
			if (mirror.connect()) {
                ArrayList<String> cmd;
                
				if (!mirror.copyToMirror(file, ".")) { // TODO .
					isValid = false;
					return isValid();
				}
				
				cmd = getCDCmd(mirror.getTestBedPath());
				cmd.add("unzip");
				cmd.add(file.getName());
				if (!mirror.execute(GGUtil.toCmdline(cmd))) {
					isValid = false;
					return isValid();
				}

				GGCompiler compiler = localTB.getCompiler(language);
System.out.println("||" + compiler.relativeDir);
				ArrayList<ArrayList<String>> compilerCommands = compiler.getCompilerCommands();
				for (ArrayList<String> compcmd : compilerCommands) {
					cmd = getCDCmd(mirror.getTestBedPath() + "/" + testbedName + "/" + compiler.relativeDir);
					cmd.addAll(compcmd);
//					cmd.add(";");
//					cmd.add("echo");
//					cmd.add("$?");
					log.append(">");
					log.append(GGUtil.toCmdline(compcmd));
					log.append('\n');
					GGCommandResult compileResult = mirror.execRes(GGUtil.toCmdline(cmd));
					if (null == compileResult) {
						log.append("Internal error in compiling solution");
						log.append('\n');
						isValid = false;
						return isValid();
					}
					log.append(compileResult.getLog());
					log.append('\n');
					log.append("Exit code: ");
					log.append(compileResult.getExitCode());
					log.append('\n');
					if (compileResult.getExitCode() != 0) {
						isValid = false;
						return isValid();
					}
				}
				
				cmd = getCDCmd(mirror.getTestBedPath() + "/" + testbedName);
				cmd.add("zip");
				cmd.add("-r");
				cmd.add("../" + testbedName + "_compiled.zip");
				cmd.add("*");
				if (!mirror.execute(GGUtil.toCmdline(cmd))) {
					isValid = false;
					return isValid();
				}
				
				if (!mirror.copyFromMirror(testbedName + "_compiled.zip", file.getParentFile())) {
					isValid = false;
					return isValid();
				}
				m_compiledZip = new File(file.getParentFile(), testbedName + "_compiled.zip");

	
//				m_commandline = getCDCmd(compiler.relativeDir);
//				m_commandline = getCDCmd(mirror.getTestBedPath() + "/" + testbedName);
				GGMirror mirror_jail = tbf.getMirror("test" + nr);
				m_commandline = getCDCmd(mirror_jail.getTestBedPath());
				ArrayList<String> prog_commandline = compiler.getProgramsCommand();
if (prog_commandline.get(0).equals("java"))
  prog_commandline.set(0, "/usr/bin/java");
//	prog_commandline.set(0, "/usr/lib/jvm/java-6-openjdk/jre/bin/java");
				m_commandline.addAll(prog_commandline);

//                // clean transfer data
//                cmd = getCDCmd(mirror.getTestBedPath());
//                cmd.add("cd");
//                cmd.add("/home/jail/gg_transfer/");
//                cmd.add(";");
//                cmd.add("rm");
//                cmd.add("-rf");
//                cmd.add("*");
//                if (!mirror.execute(GGUtil.toCmdline(cmd))) {
//                    isValid = false;
//                    return isValid();
//                }
//                
//				// copy so that jane can access
//                cmd = getCDCmd(mirror.getTestBedPath());
//                cmd.add("cd");
//                cmd.add(testbedName);
//                cmd.add(";");
//                cmd.add("cp");
//                cmd.add("-r");
//                cmd.add("*");
//                cmd.add("/home/jail/gg_transfer/");
//                if (!mirror.execute(GGUtil.toCmdline(cmd))) {
//                    isValid = false;
//                    return isValid();
//                }
				
				// remove data
				cmd = getCDCmd(mirror.getTestBedPath());
				cmd.add("rm");
				cmd.add("-rf");
				cmd.add(testbedName);
				cmd.add(testbedName + ".zip");
				cmd.add(m_compiledZip.getName());
				if (!mirror.execute(GGUtil.toCmdline(cmd))) {
					isValid = false;
					return isValid();
				}

//********************/
if (false) throw new GGProcessException(null, null, 0, null);
				// copy to jail user



/**************

				GGMirror mirror_jail = tbf.getMirror("test" + nr);
				
//String xxxx_path = "/home/jail/jane/home/data";
String xxxx_path = "/home/ggi/data";
//				if (!mirror_jail.copyToMirrorAbsolute(m_compiledZip, xxxx_path, m_compiledZip.getName())) { // TODO .
//					isValid = false;
//					return isValid();
//				}
                try {
                    if (!mirror_jail.connect()) {
                        isValid = false;
                        return isValid();
                    }

                    if (!mirror_jail.copyToMirror(m_compiledZip, ".")) { // TODO .
                        isValid = false;
                        return isValid();
                    }
//                    // clear ?
//                    cmd = getCDCmd(mirror_jail.getTestBedPath());
//                    cmd.add("rm");
//                    cmd.add("-rf");
//                    cmd.add("*");
//                    if (!mirror_jail.execute(GGUtil.toCmdline(cmd))) {
//                        isValid = false;
//                        return isValid();
//                    }
//                    
//                    // cp
//                    cmd = getCDCmd(mirror_jail.getTestBedPath());
//                    cmd.add("ls");
//                    cmd.add("/");
//                    cmd.add(";");
//                    cmd.add("cp");
//                    cmd.add("-r");
//                    cmd.add("*");
//                    cmd.add("~");
//                    if (!mirror_jail.execute(GGUtil.toCmdline(cmd))) {
//                        isValid = false;
//                        return isValid();
//                    }
                } finally {
                    mirror_jail.disconnect();
                }
                
****************/
                // ... copied to jail

//                // clean transfer data
//                cmd = getCDCmd(mirror.getTestBedPath());
//                cmd.add("cd");
//                cmd.add("/home/jail/gg_transfer/");
//                cmd.add(";");
//                cmd.add("rm");
//                cmd.add("-rf");
//                cmd.add("*");
//                if (!mirror.execute(GGUtil.toCmdline(cmd))) {
//                    isValid = false;
//                    return isValid();
//                }
                
                //////////////////////////////////////////////
			} else {
				isValid = false;
				return isValid();
			}
		} catch (GGProcessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			isValid = false;
			return isValid();
		} finally {
			mirror.disconnect();
		}
		
		return isValid();
	}
	
	public ArrayList<String> getCDCmd(String path) {
		ArrayList<String> cmd = new ArrayList<String>();
		cmd.add("cd");
		cmd.add("~");
		cmd.add(";");
		cmd.add("cd");
		cmd.add(path);
		cmd.add(";");
		return cmd;
	}
	
	@Override
	public boolean isValid() {
		return isValid;
	}

	@Override
	public String getLog() {
		// TODO Auto-generated method stub
		return log.toString();
	}

	@Override
	public GGConnection createConnection() throws IOException {
		return new GGMirroredConnection(this);
	}

	public GGConnection createConnection(boolean runOnly) throws IOException {
		return new GGMirroredConnection(this, runOnly);
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub

	}

	public void setInvalid(Exception e) {
		this.isValid = false;
		this.exception = e;
	}
	
}
